package com.commerce.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.commerce.common.entity.FlashSale;
import com.commerce.common.entity.FlashSaleProduct;
import com.commerce.product.constant.RedisConstant;
import com.commerce.product.mapper.FlashSaleMapper;
import com.commerce.product.mapper.FlashSaleProductMapper;
import com.commerce.product.service.FlashSaleStockService;
import com.commerce.product.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 秒杀库存服务实现
 */
@Slf4j
@Service
public class FlashSaleStockServiceImpl implements FlashSaleStockService {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private FlashSaleMapper flashSaleMapper;

    @Autowired
    private FlashSaleProductMapper flashSaleProductMapper;

    @Override
    public void preloadFlashSaleStock(Long flashSaleId) {
        try {
            log.info("开始预热秒杀活动库存: {}", flashSaleId);
            
            // 查询秒杀活动的所有商品
            LambdaQueryWrapper<FlashSaleProduct> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlashSaleProduct::getFlashSaleId, flashSaleId)
                   .eq(FlashSaleProduct::getStatus, 1); // 只预热上架的商品
            
            List<FlashSaleProduct> products = flashSaleProductMapper.selectList(wrapper);
            
            if (products == null || products.isEmpty()) {
                log.warn("秒杀活动{}没有找到商品", flashSaleId);
                return;
            }
            
            // 预热每个商品的库存
            for (FlashSaleProduct product : products) {
                preloadSingleProductStock(product);
            }
            
            log.info("秒杀活动{}库存预热完成，共预热{}个商品", flashSaleId, products.size());
            
        } catch (Exception e) {
            log.error("预热秒杀活动{}库存失败: {}", flashSaleId, e.getMessage(), e);
        }
    }

    @Override
    public void preloadSingleProductStock(FlashSaleProduct flashSaleProduct) {
        try {
            String stockKey = RedisConstant.buildFlashSaleStockKey(
                flashSaleProduct.getFlashSaleId(), flashSaleProduct.getProductId());
            
            // 设置库存到Redis，过期时间为24小时
            redisUtil.setStock(stockKey, flashSaleProduct.getStock(), 
                             RedisConstant.FLASH_SALE_EXPIRE_TIME);
            
            // 同时缓存商品信息
            String productKey = RedisConstant.buildFlashSaleProductKey(
                flashSaleProduct.getFlashSaleId(), flashSaleProduct.getProductId());
            redisUtil.set(productKey, flashSaleProduct, RedisConstant.FLASH_SALE_EXPIRE_TIME);
            
            log.info("预热商品库存成功: 活动ID={}, 商品ID={}, 库存={}", 
                    flashSaleProduct.getFlashSaleId(), 
                    flashSaleProduct.getProductId(), 
                    flashSaleProduct.getStock());
            
        } catch (Exception e) {
            log.error("预热单个商品库存失败: {}", e.getMessage(), e);
        }
    }

    @Override
    public boolean deductStock(Long flashSaleId, Long productId, Integer quantity) {
        try {
            String stockKey = RedisConstant.buildFlashSaleStockKey(flashSaleId, productId);
            
            // 使用Lua脚本原子性扣减库存
            long result = redisUtil.deductStock(stockKey, quantity);
            
            if (result >= 0) {
                log.info("库存预减成功: 活动ID={}, 商品ID={}, 扣减数量={}, 剩余库存={}", 
                        flashSaleId, productId, quantity, result);
                return true;
            } else if (result == -2) {
                log.warn("库存不足: 活动ID={}, 商品ID={}, 需要数量={}", 
                        flashSaleId, productId, quantity);
                return false;
            } else {
                log.warn("库存不存在: 活动ID={}, 商品ID={}", flashSaleId, productId);
                return false;
            }
            
        } catch (Exception e) {
            log.error("库存预减失败: 活动ID={}, 商品ID={}, 数量={}, 错误: {}", 
                     flashSaleId, productId, quantity, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public void rollbackStock(Long flashSaleId, Long productId, Integer quantity) {
        try {
            String stockKey = RedisConstant.buildFlashSaleStockKey(flashSaleId, productId);
            
            // 回滚库存
            Long newStock = redisUtil.increment(stockKey, quantity, 
                                              RedisConstant.FLASH_SALE_EXPIRE_TIME);
            
            log.info("库存回滚成功: 活动ID={}, 商品ID={}, 回滚数量={}, 当前库存={}", 
                    flashSaleId, productId, quantity, newStock);
            
        } catch (Exception e) {
            log.error("库存回滚失败: 活动ID={}, 商品ID={}, 数量={}, 错误: {}", 
                     flashSaleId, productId, quantity, e.getMessage(), e);
        }
    }

    @Override
    public Integer getRedisStock(Long flashSaleId, Long productId) {
        try {
            String stockKey = RedisConstant.buildFlashSaleStockKey(flashSaleId, productId);
            return redisUtil.getStock(stockKey);
        } catch (Exception e) {
            log.error("获取Redis库存失败: 活动ID={}, 商品ID={}, 错误: {}", 
                     flashSaleId, productId, e.getMessage(), e);
            return null;
        }
    }

    @Override
    @Transactional
    public void syncStockToDatabase(Long flashSaleId) {
        try {
            log.info("开始同步库存到数据库: 活动ID={}", flashSaleId);
            
            // 查询该活动的所有商品
            LambdaQueryWrapper<FlashSaleProduct> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlashSaleProduct::getFlashSaleId, flashSaleId);
            List<FlashSaleProduct> products = flashSaleProductMapper.selectList(wrapper);
            
            for (FlashSaleProduct product : products) {
                Integer redisStock = getRedisStock(flashSaleId, product.getProductId());
                if (redisStock != null && !redisStock.equals(product.getStock())) {
                    // 更新数据库库存
                    product.setStock(redisStock);
                    product.setSoldCount(product.getStock() - redisStock);
                    flashSaleProductMapper.updateById(product);
                    
                    log.info("同步库存: 活动ID={}, 商品ID={}, 数据库库存={}, Redis库存={}", 
                            flashSaleId, product.getProductId(), product.getStock(), redisStock);
                }
            }
            
            log.info("库存同步完成: 活动ID={}", flashSaleId);
            
        } catch (Exception e) {
            log.error("同步库存到数据库失败: 活动ID={}, 错误: {}", flashSaleId, e.getMessage(), e);
        }
    }

    @Override
    public void clearStockCache(Long flashSaleId) {
        try {
            // 查询该活动的所有商品
            LambdaQueryWrapper<FlashSaleProduct> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlashSaleProduct::getFlashSaleId, flashSaleId);
            List<FlashSaleProduct> products = flashSaleProductMapper.selectList(wrapper);
            
            for (FlashSaleProduct product : products) {
                String stockKey = RedisConstant.buildFlashSaleStockKey(flashSaleId, product.getProductId());
                String productKey = RedisConstant.buildFlashSaleProductKey(flashSaleId, product.getProductId());
                
                redisUtil.delete(stockKey);
                redisUtil.delete(productKey);
            }
            
            log.info("清除库存缓存完成: 活动ID={}", flashSaleId);
            
        } catch (Exception e) {
            log.error("清除库存缓存失败: 活动ID={}, 错误: {}", flashSaleId, e.getMessage(), e);
        }
    }

    @Override
    public boolean checkStock(Long flashSaleId, Long productId, Integer quantity) {
        Integer stock = getRedisStock(flashSaleId, productId);
        return stock != null && stock >= quantity;
    }

    @Override
    public List<Long> getActiveFlashSaleIds() {
        try {
            LocalDateTime now = LocalDateTime.now();
            LambdaQueryWrapper<FlashSale> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlashSale::getStatus, 1) // 进行中的活动
                   .le(FlashSale::getStartTime, now)
                   .ge(FlashSale::getEndTime, now);
            
            List<FlashSale> activeFlashSales = flashSaleMapper.selectList(wrapper);
            return activeFlashSales.stream()
                                  .map(FlashSale::getId)
                                  .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取活跃秒杀活动失败: {}", e.getMessage(), e);
            return List.of();
        }
    }

    @Override
    public void preloadAllActiveFlashSaleStock() {
        try {
            List<Long> activeFlashSaleIds = getActiveFlashSaleIds();
            log.info("开始预热所有活跃秒杀活动库存，共{}个活动", activeFlashSaleIds.size());

            for (Long flashSaleId : activeFlashSaleIds) {
                preloadFlashSaleStock(flashSaleId);
            }

            log.info("所有活跃秒杀活动库存预热完成");
        } catch (Exception e) {
            log.error("预热所有活跃秒杀活动库存失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 定时预热库存任务 - 每5分钟执行一次
     */
    @Scheduled(fixedRate = 300000) // 5分钟
    public void scheduledPreloadStock() {
        log.info("定时预热库存任务开始执行");
        preloadAllActiveFlashSaleStock();
    }

    /**
     * 定时同步库存任务 - 每30分钟执行一次
     */
    @Scheduled(fixedRate = 1800000) // 30分钟
    public void scheduledSyncStock() {
        log.info("定时同步库存任务开始执行");
        List<Long> activeFlashSaleIds = getActiveFlashSaleIds();
        for (Long flashSaleId : activeFlashSaleIds) {
            syncStockToDatabase(flashSaleId);
        }
    }
}
